package com.bawei.hgshop.common;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;


public class EsUtil<ET> {
	
	ElasticsearchTemplate esTemplate;
	
	
	/**
	 * 
	 * @param esTemplate
	 */
	public EsUtil(ElasticsearchTemplate esTemplate) {
		super();
		this.esTemplate = esTemplate;
	}
	

	/**
	 * 
	 * @param page
	 * @param pageSize
	 * @param key
	 * @param queryFileds
	 * @param hlFields
	 * @param sortFields
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public PageInfo<ET> myHlQuery(int page,  // 页码
			int pageSize,//每页的大小
			String key,//搜索的关键字
			String []queryFileds, //要搜索的字段
			String hlFields[],//高亮的字段
			String []sortFields,//排序字段
			Class clazz  //数据的类型  实际上就是T
			) {
		
		
		// 构建多字段查询
		MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery(key,queryFileds);
		//QueryBuilders.rangeQuery("").from("").to("").;
		
		//构建高亮字段
		HighlightBuilder.Field []hlFlds = new HighlightBuilder.Field[hlFields.length];
		for (int i = 0; i < hlFields.length; i++) {
			hlFlds[i] = new HighlightBuilder.Field(hlFields[i]);
		}
		
		// 构建分页
		//PageRequest pageRequest= PageRequest.of(page, pageSize, Sort.Direction.ASC);
		PageRequest pageRequest= PageRequest.of(page - 1, pageSize);
		//PageRequest pageRequest= PageRequest.of(page - 1, pageSize, Sort.by(Sort.Direction.ASC, sortFields));
		//构建查询集合
		NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(multiMatchQuery).
				withHighlightFields(hlFlds)
				.withHighlightBuilder(
					new HighlightBuilder().preTags("<font color=red>").postTags("</font>"))
				.withPageable(pageRequest)
				.build();
		
		// 进行查询
		@SuppressWarnings("unchecked")
		AggregatedPage<ET> queryForPage = esTemplate.queryForPage(query, clazz, new SearchResultMapper() {

			@Override
			public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
				// TODO Auto-generated method stub
				//当前页的数据
				List<T> list = new ArrayList();
				
				// 获取命中的数据
				SearchHits hits = response.getHits();
				
				long totalHits = hits.getTotalHits();// 被命中的总数
				
				// 对于命中的数据进行逐条处理
				for (SearchHit hit : hits) {
					// 当前条数据的映射的map
					Map<String, Object> sourceAsMap = hit.getSourceAsMap();
					//将数据转换成对象
					T t = JSON.parseObject(JSON.toJSONString(sourceAsMap), clazz);
					
					// 遍历所有的高亮字段
					hit.getHighlightFields().forEach((k,v)->{
						try {
							// 内容替换成高亮的
							BeanUtils.copyProperty(t, k, v.getFragments()[0]);
						} catch (IllegalAccessException | InvocationTargetException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					});
					//	
					list.add(t);
				}
				return  new AggregatedPageImpl(list, pageable, totalHits);
			}
			
		});
		//forList.forEach(x->{ System.out.println("x is " + x);});
		
		// Mybatis中的分页对象
		Page pageList = new Page<ET>(page, pageSize);
		// 加入集合
		pageList.addAll(queryForPage.getContent());
		// 设置总记录数
		pageList.setTotal(queryForPage.getTotalElements());
		// 转换成mybatis中的pageInfo对象
		PageInfo pageInfo = new PageInfo<ET>(pageList);

		// 返回值
		return pageInfo;
	}
	
	/**
	 * 
	 * @param id
	 * @param es
	 */
	public void save(String id, ET es) {
		// TODO Auto-generated method stub
		IndexQuery query = new IndexQueryBuilder().withId(id).withObject(es).build();
		esTemplate.index(query);
	}


	/**
	 * 
	 * @param clazz
	 * @param id
	 */
	public void remove(Class clazz,String id) {
		// TODO Auto-generated method stub
		esTemplate.delete(clazz, id);
	}
}
	

